const { app, BrowserWindow, Menu, nativeTheme, globalShortcut, ipcMain, dialog } = require('electron')
const { SerialPort } = require('serialport')
const path = require('path')
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
import icon from '../../resources/icon.png?asset'

const network = require(path.join(__dirname, '../../module/network'))
const card = require(path.join(__dirname, '../../module/card'))
const lock = require(path.join(__dirname, '../../module/lock'))

require('events').EventEmitter.defaultMaxListeners = 0;
// 保持对window对象的全局引用，如果不这么做的话，当JavaScript对象被
// 垃圾回收的时候，window对象将会自动的关闭
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'; // 去除安全警告

let mainWindow
function createWindow() {
  Menu.setApplicationMenu(null)
  // Create the browser window.
  mainWindow = new BrowserWindow({
    title: 'TIMS-Workstation',
    width: 1600,
    height: 1024,
    frame: true,
    show: false,
    autoHideMenuBar: true,
    fullscreen: false,
    resizable: true, // 用于决定窗口是否可被用户手动调整大小
    maximizable: true, // 设置用户是否可以手动最大化窗口
    ...(process.platform === 'linux' ? { icon } : {}),
    webPreferences: {
      nodeIntegration: true, // 是否启用Node integration1
      nativeWindowOpen: true,
      contextIsolation: false,
      enableRemoteModule: true,
      nodeIntegrationInWorker: true, // 是否开启多线程
      preload: path.join(__dirname, '../preload/index.js'),
      sandbox: false
    }
  })

  /*******************实现代码************************** */
  mainWindow.webContents.session.on('will-download', (event, item, webContents) => {
    //设置文件存放位置，如果用户没有设置保存路径，Electron将使用默认方式来确定保存路径（通常会提示保存对话框）
    item.setSavePath(savepath+'/'+fileName)
    console.log(savepath + '/'+fileName)
    item.on('updated', (event, state) => {
      if (state === 'interrupted') {
        console.log('Download is interrupted but can be resumed')
        mainWindow.webContents.send('downstate', 'cancel')
      } else if (state === 'progressing') {
        if (item.isPaused()) {
          console.log('Download is paused')
        } else {
          console.log(`Received bytes: ${item.getReceivedBytes()}`)
          mainWindow.webContents.send('downstate', 'start')
        }
      }
    })
    item.once('done', (event, state) => {
      if (state === 'completed') {
        console.log('Download successfully')
        //回显 调用渲染进程方法
        mainWindow.webContents.send('downstate', state)
      } else {
        console.log(`Download failed: ${state}`)
        //回显 调用渲染进程方法
        mainWindow.webContents.send('downstate', state)
      }
    })
  })
/*******************实现代码************************** */


  // 在开发环境和生产环境均可通过快捷键打开devTools
  globalShortcut.register('CommandOrControl+i', function () {
    mainWindow.webContents.openDevTools()
  })

  mainWindow.on('ready-to-show', () => {
    mainWindow.show()
  })

  mainWindow.webContents.setWindowOpenHandler((details) => {
    shell.openExternal(details.url)
    return { action: 'deny' }
  })

  //基于electronic-vite-cli的渲染器HMR。
  //加载用于开发的远程URL或用于生产的本地html文件。

  if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
    mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
  } else {
    mainWindow.loadFile(path.join(__dirname, '../renderer/index.html'))
  }

  mainWindow.on("close", e => {
    const choice = dialog.showMessageBoxSync(mainWindow, {
      type: "info",
      buttons: ["取消", "直接退出"],
      title: "TIMS信息提示",
      detail: '退出TIMS',
      message: "您确定要退出TIMS吗？",
      defaultId: 1,
      cancelId: 0
    });

    if (choice === 0) {
        e.preventDefault();
    }
  })

  // 之后会进入下面这个方法
  mainWindow.on('closed', () => {
      //main就是主程序要根据实际定义
      app.quit();
  })
 
}



//当Electron完成时，将调用此方法
//初始化并准备创建浏览器窗口。
//某些API只能在此事件发生后使用。
app.whenReady().then(() => {
  // 为windows设置应用程序用户模型id
  electronApp.setAppUserModelId('TIMS')

  //开发中默认按F12打开或关闭DevTools
  //在生产中忽略CommandOrControl+R。
  // see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils
  app.on('browser-window-created', (_, window) => {
    optimizer.watchWindowShortcuts(window)
  })

  app.on('activate', function () {
    //在macOS上，当出现以下情况时，通常会在应用程序中重新创建窗口
    //单击dock图标后，没有其他打开的窗口。
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

//关闭所有窗口后退出，macOS除外。在那里，这很常见
//让应用程序及其菜单栏保持活动状态，直到用户退出
//显式使用Cmd+Q。
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.whenReady().then(() => {
  nativeTheme.themeSource = 'dark'
  app.commandLine.appendSwitch('ignore-certificate-errors')
  createWindow()
  app.on('activate', () => {
      if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })

})


// Electron 会在初始化后并准备
// 创建浏览器窗口时，调用这个函数。
// 部分 API 在 ready 事件触发后才能使用。
var savepath = ''
var fileName = ''
app.on('ready', () => {
    // 监听子页面传送的信息
    //1.1 异步
    ipcMain.on('version',(e,val)=>{
        // console.log('主线程main.js接收到渲染线程render.js异步发送过来的值：'+val);
        var info = require(path.join(__dirname, '../../package.json'))
        console.log(info)
        var version = info.version;
        e.sender.send('version',version) // 返回版本号给渲染进程
    })
    
    // 监听热更新
    ipcMain.on('upgrading', (evt, url) => {
        console.log('我接受到了更新提示')
        upgradeFn(url)
    })

    // 退出app
    ipcMain.on('closeApp',function (res) {
        app.quit()
    })

    // 重启app
    ipcMain.on('appRelaunch',function (res) {
        app.relaunch()
        app.exit()
    })

    ipcMain.on('openPage', (e, val) => {
        // e.sender.send('returnOpenPage', '通信成功!') // 返回版本号给渲染进程
        // 切换到主页面
        mainWindow.loadFile(val+'.html')
    })

    ipcMain.on('backPage', (e, val) => {
        e.sender.send('returnOpenPage', '通信成功!') // 返回版本号给渲染进程
        // console.log(val)
        // 切换到主页面
        mainWindow.loadFile(val+'.html')
    })


})


// 禁止程序多开
const gotTheLock = app.requestSingleInstanceLock()
if (!gotTheLock) {
  app.quit()
}

// 桌面通知
const NOTIFICATION_TITLE = 'Basic Notification'
const NOTIFICATION_BODY = 'Notification from the Main process'

function showNotification () {
  new Notification({ title: NOTIFICATION_TITLE, body: NOTIFICATION_BODY }).show()
}



// 热更新应用程序

const https = require('https')
const fs = require('fs')
// const dir = path.resolve(__dirname, './resources')
const dir = path.resolve(__dirname, '../')

var AdmZip = require('adm-zip')

function upgradeFn (appResourcesUrl) {
    mainWindow.webContents.send('hot-updata-error','更新文件下载完成,安装时错误了,错误信息:'+dir)
    var destUrl = `${dir}\\app.zip`
    // var zip = new AdmZip(destUrl)
    // zip.getEntries()
    // zip.extractAllTo(dir, true)
    // deleteFile(destUrl)
    // mainWindow.webContents.send('isUpdateHotNow')

    downloadFile(appResourcesUrl, destUrl, (state, data) => {
        if (state === 'progress') {
            mainWindow.webContents.send('hotDownloadProgress', data)
        } else if (state === 'Download completed') {

        } else if (state === 'finish') {
            console.log(state)
            try {
                mainWindow.webContents.send('hot-updata-error','更新文件下载完成')
                unzip(destUrl,dir)
                // deleteFile(destUrl)

                mainWindow.webContents.send('isUpdateHotNow')
            } catch (err) {
                console.log(err)
                    console.log(destUrl)
                    mainWindow.webContents.send('hot-updata-error','更新文件下载完成,安装时错误了,错误信息:'+err)
            }
        } else if (state === 'error') {
            mainWindow.webContents.send('hot-updata-error','更新失败了!')
        }

        
    })
}
  /*
   * url 网络文件地址
   * dest 文件存储位置
   * cb 回调函数
   */
const downloadFile = (url, dest, cb = () => {} ) => {
    const stream = fs.createWriteStream(dest)
    mainWindow.webContents.send('hot-updata-error','更新文件下载完成,安装时错误了,错误信息:'+stream)
    https.get(url, (res) => {
      if (res.statusCode !== 200) {
        cb('error', 'response.statusCode error:' + res.statusCode)
        return
      }
      // 进度
      const len = parseInt(res.headers['content-length']) // 文件总长度
      let cur = 0
      const total = (len / 1048576).toFixed(2) // 转为M 1048576 - bytes in  1Megabyte
      res.on('data', function (chunk) {
        cur += chunk.length
        const progress = (100.0 * cur / len).toFixed(2) // 当前下载进度百分比
        const currProgress = (cur / 1048576).toFixed(2) // 当前下载大小
        // console.log(progress, currProgress, total)
        cb('progress', progress)
      })
      res.on('end', () => {
        cb('Download completed')
      })
      // 超时,结束等
      stream.on('finish', () => {
        stream.close(cb('finish'))
      }).on('error', (err) => {
        deleteFile(dest)
        if (cb) cb('error', 'stream error:' + err.message)
      })
      res.pipe(stream)
    })
  }
  /*
   *  删除文件
   */
  function deleteFile (url) {
    fs.unlink(url, function (err) {
      if (err) {
        
      }
    })
  }


  /**
 * unzip
 *   zipFile，待解压缩的zip文件
 *   destFolder，解压缩后存放的文件夹
 */
function unzip(zipFile, destFolder){
    var zip = new AdmZip(zipFile);
    
    var zipEntries = zip.getEntries();
    for(var i=0; i<zipEntries.length; i++){
        var entry = zipEntries[i];
        // entry.entryName = iconv.decode(entry.rawEntryName, 'gbk');
    }
    
    zip.extractAllTo(destFolder, true);

}